#ifndef PSO_HPP_
#	define PSO_HPP_

#	include "PSOParticle.hpp"
#   include <ctime>

// note : prendre la meilleure solution et balancer de la vnd dessus

class PSO
{
	public:
		PSO(	
				VRPTW& 								inVRPTW,
				unsigned							inVehiclesMax,
				unsigned 							inNParticles,
				unsigned 							inNeighborhoodSize,
				const std::pair<double, double>&	inInertiaRange,
				double								inAccP,
				double								inAccG,
				double								inAccL,
				double								inAccN,
				unsigned							inMaxIt,
				const std::pair<double, double>&	inVeloRange,
				const std::pair<double, double>&	inPosRange
				
				)
			: 	psoVRPTW(inVRPTW),
				psoVehiclesMax(inVehiclesMax),
				psoGBest(inVRPTW.size() + (inVehiclesMax << 1)),
				psoParticles(inNParticles, PSOParticle(inVRPTW, inVehiclesMax)),
				psoParticlesTmp(inNParticles, PSOParticle(inVRPTW, inVehiclesMax)),
				psoParticlesByDistance(inNParticles),
				psoNeighborhoodSize(inNeighborhoodSize),
				psoInertiaRange(inInertiaRange),
				psoU(0),
				psoAccP(inAccP),
				psoAccG(inAccG),
				psoAccL(inAccL),
				psoAccN(inAccN),
				psoMaxIt(inMaxIt),
				psoVeloRange(inVeloRange),
				psoPosRange(inPosRange)
		{
			try
			{
				/* attention au malloc ici, il faut adapter en fonction
				 * du nombre de vehicles max
				 * */
				psoParticleBFDR = new unsigned[(inVRPTW.size() * 3) * inNParticles];
				std::cout << "building PSO" << std::endl;
			}
			catch(std::bad_alloc&)
			{
				assert(false);
			}
		}
	
		~PSO()
		{			
			delete [] psoParticleBFDR;
		}
	
		void	execute();
		void	resetD(unsigned inNVehicles);
	
	protected:
		VRPTW&			psoVRPTW;
		
        clock_t         psoInitClock;
		unsigned		psoVehiclesMax;
		
		PSOVector		psoGBest;
		
		unsigned*		psoParticleBFDR;
		
		std::vector<PSOParticle>	psoParticles;
		std::vector<PSOParticle>	psoParticlesTmp;
		std::vector<std::multimap<double, PSOParticle*> >	psoParticlesByDistance;
		
		
		unsigned					psoNeighborhoodSize;
		std::pair<double, double>	psoInertiaRange;
		
		double			psoInertia;
		double			psoU;
		double			psoAccP;
		double 			psoAccG;
		double			psoAccL;
		double			psoAccN;
		
		
		
		unsigned		psoMaxIt;
		unsigned		psoIt;
		
		Sol::Eval		psoEval;
		
		std::pair<double, double>	psoVeloRange;
		std::pair<double, double>	psoPosRange;
		
		
		void	init();
};

#endif
